package com.nixsolutions.controller;

import com.nixsolutions.bean.User;
import com.nixsolutions.form.UserForm;
import com.nixsolutions.service.RoleService;
import com.nixsolutions.service.UserService;
import com.nixsolutions.validator.UserValidator;
import java.security.Principal;
import java.sql.Date;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 *
 * @author yakimovich
 */
@Controller
public class UserController {

    private final static org.apache.commons.logging.Log logger 
            = LogFactory.getLog(UserController.class);
    @Autowired
    private UserService userService;
    
    @Autowired
    private RoleService roleService;
    
    @Autowired
    private UserValidator userValidator;

    public UserController() {
    }

    public UserService getUserService() {
        return userService;
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    public RoleService getRoleService() {
        return roleService;
    }

    public void setRoleService(RoleService roleService) {
        this.roleService = roleService;
    }

    public UserValidator getUserValidator() {
        return userValidator;
    }

    public void setUserValidator(UserValidator userValidator) {
        this.userValidator = userValidator;
    }

    @RequestMapping(value = "/login")
    public String home(Model model) {
        return "home";
    }

    @RequestMapping(value = "/index")
    public String index(Principal principal, Model model) {

        String name = principal.getName();
        User user = userService.findByLogin(name);

        if (user.getRole().getName().equalsIgnoreCase("ROLE_ADMIN")) {
            model.addAttribute("lastname", user.getLastName());
            model.addAttribute("users", userService.findAll());
            return "adminPage";
        } else {
            model.addAttribute("firstname", user.getFirstName());
            return "welcome";
        }
    }

    @RequestMapping(value = "/registration", method = RequestMethod.GET)
    public String registrShow(ModelMap model) {

        model.put("userForm", new UserForm());
        return "registerPage";
    }

    @RequestMapping(value = "/loginfailure", method = RequestMethod.GET)
    public String loginError(Model model) {

        model.addAttribute("error", "Invalid login or password");
        return "home";
    }

    @RequestMapping(value = "/accessDenied", method = RequestMethod.GET)
    public String accessDenied(Model model) {

        model.addAttribute(
                "error", "You haven't permissions for this page!");
        return "home";
    }

    @RequestMapping(value = "/logout", method = RequestMethod.GET)
    public String logout(Model model) {

        return "home";
    }

    @RequestMapping(value = "/adminNewUser", method = RequestMethod.GET)
    public String newUserGet(Principal principal, Model model) {

        String name = principal.getName();
        User user = userService.findByLogin(name);

        model.addAttribute("lastname", user.getLastName());
        model.addAttribute("userForm", new UserForm());

        return "adminAddUser";
    }

    @RequestMapping(value = "/adminAddUser", method = RequestMethod.POST)
    public String newUserPost(Principal principal,
            @ModelAttribute("userForm") UserForm userForm,
            BindingResult result, Model model) {

        String name = principal.getName();
        User admin = userService.findByLogin(name);
        model.addAttribute("lastname", admin.getLastName());

        userValidator.validate(userForm, result);
        if (result.hasErrors()) {
            return "/adminAddUser";
        }
        if (null != userService.findByLogin(userForm.getLogin())) {
            model.addAttribute("error",
                    "User with such login allready exists.");
            return "adminAddUser";
        }
        if (null != userService.findByEmail(userForm.getEmail())) {
            model.addAttribute("error",
                    "User with such email allready exists.");
            return "adminAddUser";
        }

        User newUser = new User();

        newUser.setLogin(userForm.getLogin());
        newUser.setPassword(userForm.getPassword());
        newUser.setEmail(userForm.getEmail());
        newUser.setFirstName(userForm.getFirstName());
        newUser.setLastName(userForm.getLastName());
        newUser.setBirthday(Date.valueOf(userForm.getBirthday()));
        newUser.setRole(roleService.findByName(userForm.getRole()));

        try {
            userService.create(newUser);
        } catch (RuntimeException e) {
            model.addAttribute("user", newUser);
            model.addAttribute("error", e.getMessage());
            logger.error("Adding user failed", e);
            return "adminAddUser";
        }
        model.addAttribute("users", userService.findAll());
        return "adminPage";
    }

    @RequestMapping(value = "/adminEditUser", method = RequestMethod.GET)
    public String editUserGet(Principal principal,
            @RequestParam String login, Model model) {

        String name = principal.getName();
        User admin = userService.findByLogin(name);
        model.addAttribute("lastname", admin.getLastName());

        User editUser = null;

        try {
            editUser = userService.findByLogin(login);
        } catch (RuntimeException e) {
            model.addAttribute("error", e.getMessage());
            model.addAttribute("users", userService.findAll());
            return "adminPage";
        }

        model.addAttribute("user", editUser);
        model.addAttribute("userForm", new UserForm());

        return "adminModifyUser";
    }

    @RequestMapping(value = "/adminModifyUser", method = RequestMethod.POST)
    public String editUserPost(Principal principal, Model model,
            @RequestParam("id") String id,
            @ModelAttribute("userForm") UserForm userForm,
            BindingResult result) {

        String name = principal.getName();
        User admin = userService.findByLogin(name);

        model.addAttribute("lastname", admin.getLastName());

        userValidator.validate(userForm, result);

        if (result.hasErrors()) {
            User user = new User();
            user.setId(Long.parseLong(id));
            user.setLogin(userForm.getLogin());
            model.addAttribute("user", user);
            return "adminModifyUser";
        }

        User editUser = new User();

        editUser.setId(Long.parseLong(id));
        editUser.setLogin(userForm.getLogin());
        editUser.setPassword(userForm.getPassword());
        editUser.setEmail(userForm.getEmail());
        editUser.setFirstName(userForm.getFirstName());
        editUser.setLastName(userForm.getLastName());
        editUser.setBirthday(Date.valueOf(userForm.getBirthday()));
        editUser.setRole(roleService.findByName(userForm.getRole()));

        try {
            userService.update(editUser);
        } catch (RuntimeException e) {
            model.addAttribute("user", editUser);
            model.addAttribute("error", e.getMessage());
            logger.error("User editing failed", e);

            return "adminModifyUser";
        }

        model.addAttribute("users", userService.findAll());
        return "adminPage";
    }

    @RequestMapping(value = "/adminRemoveUser", method = RequestMethod.GET)
    public String deleteUserGet(@RequestParam long id, Model model) {

        User user = new User();
        user.setId(id);

        userService.remove(user);

        model.addAttribute("users", userService.findAll());

        return "adminPage";
    }

    @RequestMapping(value = "/registerPage", method = RequestMethod.POST)
    public String register(HttpServletRequest req,
            @RequestParam("recaptcha_challenge_field") String challenge,
            @RequestParam("recaptcha_response_field") String response,
            @ModelAttribute("userForm") UserForm userForm,
            BindingResult result, Model model) {

        userValidator.validate(userForm, result);
        if (result.hasErrors()) {
            return "registerPage";
        }
        if (null != userService.findByLogin(userForm.getLogin())) {
            model.addAttribute("error",
                    "User with such login allready exists.");
            return "registerPage";
        }
        if (null != userService.findByEmail(userForm.getEmail())) {
            model.addAttribute("error",
                    "User with such email allready exists.");
            return "registerPage";
        }

        User addUser = new User();

        addUser.setLogin(userForm.getLogin());
        addUser.setPassword(userForm.getPassword());
        addUser.setEmail(userForm.getEmail());
        addUser.setFirstName(userForm.getFirstName());
        addUser.setLastName(userForm.getLastName());
        addUser.setBirthday(Date.valueOf(userForm.getBirthday()));
        addUser.setRole(roleService.findByName("ROLE_USER"));

        if (!userValidator.reCaptchaValidation(req, challenge, response)) {
            model.addAttribute("user", addUser);
            model.addAttribute("error", "Captcha value is incorrect!");
            return "registerPage";
        }

        try {
            userService.create(addUser);
        } catch (RuntimeException e) {
            model.addAttribute("user", addUser);
            model.addAttribute("error", e.getMessage());
            return "registerPage";
        }

        model.addAttribute("userName", userForm.getFirstName());
        return "home";
    }
}
